pacman::p_load(tidyverse, corrr, ggplot2, lmerTest, ggeffects, sjPlot, tidyverse, heatmaply, pheatmap, gplots, RColorBrewer)
setwd("/Volumes/GoogleDrive/My Drive/Volumes/Research Project/Preference Falsification/Analysis/")
Warning: The working directory was changed to /Volumes/GoogleDrive/My Drive/Volumes/Research Project/Preference Falsification/Analysis inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
indDiffDf <- read.csv("./output/PFindDiffDf.csv")
indDiffDf[c("Rep","Info", "partyN")] <- NULL
#longDf <- read.csv("./output/PFfullDf.csv")
longDf <- read.csv("./output/PFfullDfzip.csv")
indDiffDf <- merge(indDiffDf, longDf[match(unique(longDf$subID), longDf$subID),][c("subID","Polit")], by = "subID")
indDiffDf$polStrength <- abs(7- indDiffDf$Polit )
issExpDf <- read.csv("./output/issueAgDf.csv")
longDf$partyN <- as.factor(longDf$partyN)
longDf$Rep <- as.factor(longDf$Rep)
contrasts(longDf$Rep) <- contr.sum(3)
longDf$RepN <- as.factor(longDf$RepN)
longDf$RepN <- relevel(longDf$RepN,"In")
longDf$Info <- as.factor(longDf$Info)
contrasts(longDf$Info) <- contr.sum(2)
longDf$partyN <- as.factor(longDf$partyN)
contrasts(longDf$partyN) <- contr.sum(2)
longDf <- longDf[order(longDf$subID, longDf$issues),]
demDf <- subset(longDf, partyN == "Dem")
repDf <- subset(longDf, partyN == "Rep")
shortDf1 <- longDf[!duplicated(longDf$subID),]
longDfc<- longDf[c("subID","issues","eval")]
longDfc <- longDfc[order(longDfc$subID, longDfc$issues),]
wideDf <- longDfc %>% pivot_wider(names_from = issues, values_from = eval)

corMat <- wideDf %>% select(`1`:`100`) %>% cor(.,use="pairwise.complete.obs")
corMatZ <- psych::fisherz(corMat)
corVector <- corMatZ[lower.tri(corMatZ)]
colnames(corMat) <- longDf$label[match(unique(longDf$issues), longDf$issues) ]
rownames(corMat) <- longDf$label[match(unique(longDf$issues), longDf$issues) ]
jpeg("~/Desktop/test.png", height=10, width=15, units="in",res=300)
heatmap(corMat, Colv = "Rowv", symm=TRUE, cexRow=.5, cexCol=.5)
dev.off()
null device 
          1 
jpeg("~/Desktop/test.png", height=12, width=30, units="in",res=300)
outphm<-pheatmap(corMat, fontsize_row = 6, fontsize_col = 6, angle_col = 45, angle_row =45, width=100, height = 200 )
outphm
dev.off()
null device 
          1 
outphm

out<-heatmaply::ggheatmap(corMat, grid_gap=2, colorbar_len=50, grid_size = 5 , Rowv=outphm[[1]], Colv=outphm[[2]], revC=TRUE, fontsize_row = 8.5, fontsize_col = 8.5, angle_col = 45, angle_row =45,  limits = c(-1, 1), colors = colorRampPalette(rev(brewer.pal(n = 7, name = "RdYlBu")))(100))
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

jpeg("~/Desktop/test.png", height=15, width=20, units="in",res=300)
out
dev.off()
quartz_off_screen 
                2 

library(RColorBrewer)
out<-heatmaply::ggheatmap(corMat, colorbar_len=50, grid_size = 5 , Rowv=outphm[[1]], Colv=outphm[[2]], revC=TRUE, fontsize_row = 8.5, fontsize_col = 8.5, angle_col = 45, angle_row =45,  limits = c(-1, 1), colors = colorRampPalette(rev(brewer.pal(n = 7, name = "RdYlBu")))(100))
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

out
ggsave("~/Desktop/test2.png", dpi=300,units="in",height=20,width=20)

heatmaply_cor(round(corMat,3), Rowv=outphm[[1]], Colv=outphm[[2]], revC=TRUE, fontsize_row = 2.5, fontsize_col = 2.5, angle_col = 45, angle_row =45,  limits = c(-1, 1), colors = colorRampPalette(rev(brewer.pal(n = 7, name =
  "RdYlBu")))(100) )
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
mds2<-corMat %>%
  psych::cor2dist(.) %>%
  MASS::isoMDS(k=2) %>%
  .$points %>%
  as_tibble()
initial  value 16.681209 
iter   5 value 12.639758
iter  10 value 12.193377
final  value 12.166250 
converged
Warning: The `x` argument of `as_tibble.matrix()` must have unique column names if `.name_repair` is omitted as of tibble 2.0.0.
Using compatibility `.name_repair`.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
colnames(mds2) <- c("Dim.1", "Dim.2")
library(ggpubr)
Registered S3 methods overwritten by 'car':
  method                          from
  influence.merMod                lme4
  cooks.distance.influence.merMod lme4
  dfbeta.influence.merMod         lme4
  dfbetas.influence.merMod        lme4
ggscatter(mds2, x = "Dim.1", y = "Dim.2", 
          label = longDf$label[match(unique(longDf$issues), longDf$issues) ],
          font.label = c(5, "bold", "black"),
          size = 1,
          repel = TRUE)

allDists <- tapply(longDf$eval, longDf$subID, dist)

issuesFrame <- longDf[match(unique(longDf$issues), 1:100),]

allDistsOut <- tapply(longDf$bootEvalOut, longDf$subID, dist)

allDistsIn <- tapply(longDf$bootEvalIn, longDf$subID, dist)

demIssues <- demDf[match(unique(demDf$issues), 1:100),]
repIssues <- repDf[match(unique(repDf$issues), 1:100),]

demDistM<-as.matrix(dist(c(demIssues$bootEvalIn, demIssues$bootEvalOut)))
demDistM<-as.matrix(demDistM[-(1:100),-(101:200)])
demDistV <- demDistM[lower.tri(demDistM)]

repDistM<-as.matrix(dist(c(repIssues$bootEvalIn, repIssues$bootEvalOut)))
repDistM<-as.matrix(repDistM[-(1:100),-(101:200)])
repDistV <- repDistM[lower.tri(repDistM)]

reputDist <- dist(issuesFrame$reput)
reputMatrix <- as.matrix(reputDist)
reputVector <- reputMatrix[lower.tri(reputMatrix)]

reputDDist <- dist(issuesFrame$reputD)
reputDMatrix <- as.matrix(reputDDist)
reputDVector <- reputDMatrix[lower.tri(reputDMatrix)]

honestDist <- dist(issuesFrame$honest)
honestMatrix <- as.matrix(honestDist)
honestVector <- honestMatrix[lower.tri(honestMatrix)]

changeDist <- dist(issuesFrame$change)
changeMatrix <- as.matrix(changeDist)
changeVector <- changeMatrix[lower.tri(changeMatrix)]

politicDist <- dist(issuesFrame$politic)
politicMatrix <- as.matrix(politicDist)
politicVector <- politicMatrix[lower.tri(politicMatrix)]

breadthDist <- dist(issuesFrame$breadth)
breadthMatrix <- as.matrix(breadthDist)
breadthVector <- breadthMatrix[lower.tri(breadthMatrix)]

fullMat <- as.data.frame(matrix(ncol=16))
uIds<-unique(longDf$subID)
for(i in 1:length(uIds)){
  j <- uIds[i]
  
  distMatrix <- as.matrix(allDists[[i]])
  distVector <- distMatrix[lower.tri(distMatrix)]
  
  distMatrixOut <- as.matrix(allDistsOut[[i]])
  distVectorOut <- distMatrixOut[lower.tri(distMatrixOut)]
  
  distMatrixIn <- as.matrix(allDistsIn[[i]])
  distVectorIn <- distMatrixOut[lower.tri(distMatrixIn)]
  
  if( as.character(unique(longDf$partyN[longDf$subID==j]))=="Rep" ){
    partyDistV <- repDistV
  }else if( as.character(unique(longDf$partyN[longDf$subID==j]))=="Dem" ){
    partyDistV <- demDistV
  }
  
  subMat <- cbind(data.frame(subID=j,dist=distVector,RepN=unique(longDf$RepN[longDf$subID==j]), partyN=unique(longDf$partyN[longDf$subID==j]), Info=unique(longDf$Info[longDf$subID==j]), Rep=unique(longDf$Rep[longDf$subID==j]), reputD = reputVector, reputDD = reputDVector, changeD = changeVector, honestD = honestVector, politicD = politicVector, breadthD = breadthVector, distOut = distVectorOut, distIn = distVectorIn, distParty  = partyDistV, corr = corVector ))
  names(fullMat) <- colnames(subMat)
  fullMat <- rbind(fullMat, subMat)
}

#x <- c("subID","dist")
#fullDistDf <- as.data.frame(fullMat)
#names(fullDistDf) <- x
fullDistDf <- as.data.frame(fullMat)
fullDistDf<-fullDistDf[!is.na(fullDistDf$subID),]

fullDistDf$distSTrans <- 1/(1+fullDistDf$dist)
fullDistDf$distETrans <- 1/(exp(fullDistDf$dist))

#fullDistDf <- merge(fullDistDf, longDf[c("subID","RepN","partyN","Info")], by = "subID")

fullDistDf <- merge(fullDistDf, indDiffDf, by = "subID")

colnames(fullDistDf)
 [1] "subID"        "dist"         "RepN"         "partyN"       "Info"         "Rep"          "reputD"       "reputDD"     
 [9] "changeD"      "honestD"      "politicD"     "breadthD"     "distOut"      "distIn"       "distParty"    "corr"        
[17] "distSTrans"   "distETrans"   "inTherm"      "outTherm"     "affPol"       "Extra"        "Neur"         "MLAM"        
[25] "SCS.pub"      "SCS.priv"     "SCS.sa"       "WSC"          "NFC"          "SGO.wt"       "SGO.st"       "SGO.sw"      
[33] "CSEpriv"      "CSEpub"       "CSEid"        "falsify"      "bDiffInMean"  "bDiffOutMean" "Polit"        "polStrength" 
fullDistDf <- fullDistDf %>% select(subID, dist, RepN, partyN, Info, Rep, corr, distSTrans, distETrans, affPol:falsify, Polit, polStrength)

write.csv(fullDistDf, "~/Google Drive/Volumes/Research Project/Preference Falsification/Analysis/output/distanceDf.csv")

arrow::write_parquet(fullDistDf, "~/Google Drive/Volumes/Research Project/Preference Falsification/Analysis/output/distanceDf.parquet")
longDf2c<- longDf2[c("subID","issues","eval")]
longDf2c <- longDf2c[order(longDf2c$subID, longDf2c$issues),]
wideDf <- longDf2c %>% pivot_wider(names_from = issues, values_from = eval)

corMat <- wideDf %>% select(`1`:`100`) %>% cor(.,use="pairwise.complete.obs")
corMatZ <- psych::fisherz(corMat)
corVector <- corMatZ[lower.tri(corMatZ)]
colnames(corMat) <- longDf2$label.x[match(unique(longDf2$issues), longDf2$issues) ]
rownames(corMat) <- longDf2$label.x[match(unique(longDf2$issues), longDf2$issues) ]
jpeg("~/Desktop/test.png", height=10, width=15, units="in",res=300)
heatmap(corMat, Colv = "Rowv", symm=TRUE, cexRow=.5, cexCol=.5)
dev.off()
null device 
          1 
jpeg("~/Desktop/test.png", height=12, width=30, units="in",res=300)
outphm<-pheatmap(corMat, fontsize_row = 6, fontsize_col = 6, angle_col = 45, angle_row =45, width=100, height = 200 )
outphm
dev.off()
null device 
          1 
outphm

out<-heatmaply::ggheatmap(corMat, grid_gap=2, colorbar_len=50, grid_size = 5 , Rowv=outphm[[1]], Colv=outphm[[2]], revC=TRUE, fontsize_row = 8.5, fontsize_col = 8.5, angle_col = 45, angle_row =45,  limits = c(-1, 1), colors = colorRampPalette(rev(brewer.pal(n = 7, name = "RdYlBu")))(100))
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

jpeg("~/Desktop/test.png", height=15, width=20, units="in",res=300)
out
dev.off()
quartz_off_screen 
                2 

out<-heatmaply::ggheatmap(corMat, colorbar_len=50, grid_size = 5 , Rowv=outphm[[1]], Colv=outphm[[2]], revC=TRUE, fontsize_row = 8.5, fontsize_col = 8.5, angle_col = 45, angle_row =45,  limits = c(-1, 1), colors = colorRampPalette(rev(brewer.pal(n = 7, name = "RdYlBu")))(100))
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

out
ggsave("~/Desktop/test2.png", dpi=300,units="in",height=20,width=20)

heatmaply_cor(round(corMat,3), Rowv=outphm[[1]], Colv=outphm[[2]], revC=TRUE, fontsize_row = 2.5, fontsize_col = 2.5, angle_col = 45, angle_row =45,  limits = c(-1, 1), colors = colorRampPalette(rev(brewer.pal(n = 7, name =
  "RdYlBu")))(100) )
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
mds2<-corMat %>%
  psych::cor2dist(.) %>%
  MASS::isoMDS(k=2) %>%
  .$points %>%
  as_tibble()
initial  value 18.781471 
iter   5 value 14.617077
final  value 14.331974 
converged
colnames(mds2) <- c("Dim.1", "Dim.2")
library(ggpubr)
ggscatter(mds2, x = "Dim.1", y = "Dim.2", 
          label = longDf2$label.x[match(unique(longDf2$issues), longDf2$issues) ],
          font.label = c(5, "bold", "black"),
          size = 1,
          repel = TRUE)

write.csv(fullDistDf2, "/Volumes/GoogleDrive/My Drive/Volumes/Research Project/Preference Falsification/Study 2 Analysis/output/distanceDf2.csv")
Warning in file(file, ifelse(append, "a", "w")) :
  cannot open file '/Volumes/GoogleDrive/My Drive/Volumes/Research Project/Preference Falsification/Study 2 Analysis/output/distanceDf2.csv': Resource temporarily unavailable
Error in file(file, ifelse(append, "a", "w")) : 
  cannot open the connection
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgY29ycnIsIGdncGxvdDIsIGxtZXJUZXN0LCBnZ2VmZmVjdHMsIHNqUGxvdCwgdGlkeXZlcnNlLCBoZWF0bWFwbHksIHBoZWF0bWFwLCBncGxvdHMsIFJDb2xvckJyZXdlcikKYGBgCgpgYGB7cn0Kc2V0d2QoIi9Wb2x1bWVzL0dvb2dsZURyaXZlL015IERyaXZlL1ZvbHVtZXMvUmVzZWFyY2ggUHJvamVjdC9QcmVmZXJlbmNlIEZhbHNpZmljYXRpb24vQW5hbHlzaXMvIikKaW5kRGlmZkRmIDwtIHJlYWQuY3N2KCIuL291dHB1dC9QRmluZERpZmZEZi5jc3YiKQppbmREaWZmRGZbYygiUmVwIiwiSW5mbyIsICJwYXJ0eU4iKV0gPC0gTlVMTAojbG9uZ0RmIDwtIHJlYWQuY3N2KCIuL291dHB1dC9QRmZ1bGxEZi5jc3YiKQpsb25nRGYgPC0gcmVhZC5jc3YoIi4vb3V0cHV0L1BGZnVsbERmemlwLmNzdiIpCmluZERpZmZEZiA8LSBtZXJnZShpbmREaWZmRGYsIGxvbmdEZlttYXRjaCh1bmlxdWUobG9uZ0RmJHN1YklEKSwgbG9uZ0RmJHN1YklEKSxdW2MoInN1YklEIiwiUG9saXQiKV0sIGJ5ID0gInN1YklEIikKaW5kRGlmZkRmJHBvbFN0cmVuZ3RoIDwtIGFicyg3LSBpbmREaWZmRGYkUG9saXQgKQppc3NFeHBEZiA8LSByZWFkLmNzdigiLi9vdXRwdXQvaXNzdWVBZ0RmLmNzdiIpCmxvbmdEZiRwYXJ0eU4gPC0gYXMuZmFjdG9yKGxvbmdEZiRwYXJ0eU4pCmxvbmdEZiRSZXAgPC0gYXMuZmFjdG9yKGxvbmdEZiRSZXApCmNvbnRyYXN0cyhsb25nRGYkUmVwKSA8LSBjb250ci5zdW0oMykKbG9uZ0RmJFJlcE4gPC0gYXMuZmFjdG9yKGxvbmdEZiRSZXBOKQpsb25nRGYkUmVwTiA8LSByZWxldmVsKGxvbmdEZiRSZXBOLCJJbiIpCmxvbmdEZiRJbmZvIDwtIGFzLmZhY3Rvcihsb25nRGYkSW5mbykKY29udHJhc3RzKGxvbmdEZiRJbmZvKSA8LSBjb250ci5zdW0oMikKbG9uZ0RmJHBhcnR5TiA8LSBhcy5mYWN0b3IobG9uZ0RmJHBhcnR5TikKY29udHJhc3RzKGxvbmdEZiRwYXJ0eU4pIDwtIGNvbnRyLnN1bSgyKQpsb25nRGYgPC0gbG9uZ0RmW29yZGVyKGxvbmdEZiRzdWJJRCwgbG9uZ0RmJGlzc3VlcyksXQpkZW1EZiA8LSBzdWJzZXQobG9uZ0RmLCBwYXJ0eU4gPT0gIkRlbSIpCnJlcERmIDwtIHN1YnNldChsb25nRGYsIHBhcnR5TiA9PSAiUmVwIikKc2hvcnREZjEgPC0gbG9uZ0RmWyFkdXBsaWNhdGVkKGxvbmdEZiRzdWJJRCksXQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpzZXR3ZCgifi9Hb29nbGUgRHJpdmUvVm9sdW1lcy9SZXNlYXJjaCBQcm9qZWN0L1ByZWZlcmVuY2UgRmFsc2lmaWNhdGlvbi9TdHVkeSAyIEFuYWx5c2lzLyIpCmluZERpZmZEZjIgPC0gcmVhZC5jc3YoIi4vb3V0cHV0L1BGaW5kRGlmZkRmMi5jc3YiKQpsb25nRGYyIDwtIHJlYWQuY3N2KCIuL291dHB1dC9QRmZ1bGxEZjIuY3N2IikKaXNzRXhwRGYyIDwtIHJlYWQuY3N2KCIuL291dHB1dC9pc3N1ZUFnRGYyLmNzdiIpCmxvbmdEZjIkcGFydHlOIDwtIGFzLmZhY3Rvcihsb25nRGYyJHBhcnR5TikKbG9uZ0RmMiRSZXAgPC0gYXMuZmFjdG9yKGxvbmdEZjIkUmVwKQpsb25nRGYyJFJlcCA8LSBmYWN0b3IobG9uZ0RmMiRSZXAsIGMoIk5vbiIsIlJlcCIsIkRlbSIpKQpsb25nRGYyJFJlcCA8LSByZWxldmVsKGxvbmdEZjIkUmVwLCJOb24iKQpjb250cmFzdHMobG9uZ0RmMiRSZXApIDwtIGNvbnRyLnN1bSgzKQpsb25nRGYyJFJlcE4gPC0gYXMuZmFjdG9yKGxvbmdEZjIkUmVwTikKbG9uZ0RmMiRSZXBOIDwtIHJlbGV2ZWwobG9uZ0RmMiRSZXBOLCJJbiIpCmxvbmdEZjIkSW5mbyA8LSBhcy5mYWN0b3IobG9uZ0RmMiRJbmZvKQpjb250cmFzdHMobG9uZ0RmMiRJbmZvKSA8LSBjb250ci5zdW0oMikKbG9uZ0RmMiRwYXJ0eU4gPC0gYXMuZmFjdG9yKGxvbmdEZjIkcGFydHlOKQpjb250cmFzdHMobG9uZ0RmMiRwYXJ0eU4pIDwtIGNvbnRyLnN1bSgyKQpkZW1EZiA8LSBzdWJzZXQobG9uZ0RmMiwgcGFydHlOID09ICJEZW0iKQpyZXBEZiA8LSBzdWJzZXQobG9uZ0RmMiwgcGFydHlOID09ICJSZXAiKQpsb25nRGYyIDwtIGxvbmdEZjJbb3JkZXIobG9uZ0RmMiRzdWJJRCwgbG9uZ0RmMiRpc3N1ZXMpLF0KbG9uZ0RmMiRwb2xTdHJlbmd0aCA8LSBhYnMobG9uZ0RmMiRQb2xpdCAtIDQpCnNob3J0RGYyIDwtIGxvbmdEZjJbIWR1cGxpY2F0ZWQobG9uZ0RmMiRzdWJJRCksXQppbmREaWZmRGYyIDwtIG1lcmdlKGluZERpZmZEZjIsIHNob3J0RGYyW2MoInN1YklEIiwiUG9saXQiKV0sIGJ5ID0gInN1YklEIikKYGBgCgpgYGB7cn0KbG9uZ0RmYzwtIGxvbmdEZltjKCJzdWJJRCIsImlzc3VlcyIsImV2YWwiKV0KbG9uZ0RmYyA8LSBsb25nRGZjW29yZGVyKGxvbmdEZmMkc3ViSUQsIGxvbmdEZmMkaXNzdWVzKSxdCndpZGVEZiA8LSBsb25nRGZjICU+JSBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gaXNzdWVzLCB2YWx1ZXNfZnJvbSA9IGV2YWwpCgpjb3JNYXQgPC0gd2lkZURmICU+JSBzZWxlY3QoYDFgOmAxMDBgKSAlPiUgY29yKC4sdXNlPSJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQpjb3JNYXRaIDwtIHBzeWNoOjpmaXNoZXJ6KGNvck1hdCkKY29yVmVjdG9yIDwtIGNvck1hdFpbbG93ZXIudHJpKGNvck1hdFopXQpgYGAKCmBgYHtyfQpjb2xuYW1lcyhjb3JNYXQpIDwtIGxvbmdEZiRsYWJlbFttYXRjaCh1bmlxdWUobG9uZ0RmJGlzc3VlcyksIGxvbmdEZiRpc3N1ZXMpIF0Kcm93bmFtZXMoY29yTWF0KSA8LSBsb25nRGYkbGFiZWxbbWF0Y2godW5pcXVlKGxvbmdEZiRpc3N1ZXMpLCBsb25nRGYkaXNzdWVzKSBdCmpwZWcoIn4vRGVza3RvcC90ZXN0LnBuZyIsIGhlaWdodD0xMCwgd2lkdGg9MTUsIHVuaXRzPSJpbiIscmVzPTMwMCkKaGVhdG1hcChjb3JNYXQsIENvbHYgPSAiUm93diIsIHN5bW09VFJVRSwgY2V4Um93PS41LCBjZXhDb2w9LjUpCmRldi5vZmYoKQpgYGAKCmBgYHtyfQpqcGVnKCJ+L0Rlc2t0b3AvdGVzdC5wbmciLCBoZWlnaHQ9MTIsIHdpZHRoPTMwLCB1bml0cz0iaW4iLHJlcz0zMDApCm91dHBobTwtcGhlYXRtYXAoY29yTWF0LCBmb250c2l6ZV9yb3cgPSA2LCBmb250c2l6ZV9jb2wgPSA2LCBhbmdsZV9jb2wgPSA0NSwgYW5nbGVfcm93ID00NSwgd2lkdGg9MTAwLCBoZWlnaHQgPSAyMDAgKQpvdXRwaG0KZGV2Lm9mZigpCm91dHBobQpgYGAKCmBgYHtyfQpvdXQ8LWhlYXRtYXBseTo6Z2doZWF0bWFwKGNvck1hdCwgZ3JpZF9nYXA9MiwgY29sb3JiYXJfbGVuPTUwLCBncmlkX3NpemUgPSA1ICwgUm93dj1vdXRwaG1bWzFdXSwgQ29sdj1vdXRwaG1bWzJdXSwgcmV2Qz1UUlVFLCBmb250c2l6ZV9yb3cgPSA4LjUsIGZvbnRzaXplX2NvbCA9IDguNSwgYW5nbGVfY29sID0gNDUsIGFuZ2xlX3JvdyA9NDUsICBsaW1pdHMgPSBjKC0xLCAxKSwgY29sb3JzID0gY29sb3JSYW1wUGFsZXR0ZShyZXYoYnJld2VyLnBhbChuID0gNywgbmFtZSA9ICJSZFlsQnUiKSkpKDEwMCkpCmpwZWcoIn4vRGVza3RvcC90ZXN0LnBuZyIsIGhlaWdodD0xNSwgd2lkdGg9MjAsIHVuaXRzPSJpbiIscmVzPTMwMCkKb3V0CmRldi5vZmYoKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKb3V0PC1oZWF0bWFwbHk6OmdnaGVhdG1hcChjb3JNYXQsIGNvbG9yYmFyX2xlbj01MCwgZ3JpZF9zaXplID0gNSAsIFJvd3Y9b3V0cGhtW1sxXV0sIENvbHY9b3V0cGhtW1syXV0sIHJldkM9VFJVRSwgZm9udHNpemVfcm93ID0gOC41LCBmb250c2l6ZV9jb2wgPSA4LjUsIGFuZ2xlX2NvbCA9IDQ1LCBhbmdsZV9yb3cgPTQ1LCAgbGltaXRzID0gYygtMSwgMSksIGNvbG9ycyA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwobiA9IDcsIG5hbWUgPSAiUmRZbEJ1IikpKSgxMDApKQpvdXQKZ2dzYXZlKCJ+L0Rlc2t0b3AvdGVzdDIucG5nIiwgZHBpPTMwMCx1bml0cz0iaW4iLGhlaWdodD0yMCx3aWR0aD0yMCkKYGBgCgoKCgpgYGB7cn0KaGVhdG1hcGx5X2Nvcihyb3VuZChjb3JNYXQsMyksIFJvd3Y9b3V0cGhtW1sxXV0sIENvbHY9b3V0cGhtW1syXV0sIHJldkM9VFJVRSwgZm9udHNpemVfcm93ID0gMi41LCBmb250c2l6ZV9jb2wgPSAyLjUsIGFuZ2xlX2NvbCA9IDQ1LCBhbmdsZV9yb3cgPTQ1LCAgbGltaXRzID0gYygtMSwgMSksIGNvbG9ycyA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwobiA9IDcsIG5hbWUgPQogICJSZFlsQnUiKSkpKDEwMCkgKQpgYGAKCgpgYGB7cn0KbWRzMjwtY29yTWF0ICU+JQogIHBzeWNoOjpjb3IyZGlzdCguKSAlPiUKICBNQVNTOjppc29NRFMoaz0yKSAlPiUKICAuJHBvaW50cyAlPiUKICBhc190aWJibGUoKQpjb2xuYW1lcyhtZHMyKSA8LSBjKCJEaW0uMSIsICJEaW0uMiIpCmxpYnJhcnkoZ2dwdWJyKQpnZ3NjYXR0ZXIobWRzMiwgeCA9ICJEaW0uMSIsIHkgPSAiRGltLjIiLCAKICAgICAgICAgIGxhYmVsID0gbG9uZ0RmJGxhYmVsW21hdGNoKHVuaXF1ZShsb25nRGYkaXNzdWVzKSwgbG9uZ0RmJGlzc3VlcykgXSwKICAgICAgICAgIGZvbnQubGFiZWwgPSBjKDUsICJib2xkIiwgImJsYWNrIiksCiAgICAgICAgICBzaXplID0gMSwKICAgICAgICAgIHJlcGVsID0gVFJVRSkKYGBgCgoKYGBge3J9CmFsbERpc3RzIDwtIHRhcHBseShsb25nRGYkZXZhbCwgbG9uZ0RmJHN1YklELCBkaXN0KQoKaXNzdWVzRnJhbWUgPC0gbG9uZ0RmW21hdGNoKHVuaXF1ZShsb25nRGYkaXNzdWVzKSwgMToxMDApLF0KCmFsbERpc3RzT3V0IDwtIHRhcHBseShsb25nRGYkYm9vdEV2YWxPdXQsIGxvbmdEZiRzdWJJRCwgZGlzdCkKCmFsbERpc3RzSW4gPC0gdGFwcGx5KGxvbmdEZiRib290RXZhbEluLCBsb25nRGYkc3ViSUQsIGRpc3QpCgpkZW1Jc3N1ZXMgPC0gZGVtRGZbbWF0Y2godW5pcXVlKGRlbURmJGlzc3VlcyksIDE6MTAwKSxdCnJlcElzc3VlcyA8LSByZXBEZlttYXRjaCh1bmlxdWUocmVwRGYkaXNzdWVzKSwgMToxMDApLF0KCmRlbURpc3RNPC1hcy5tYXRyaXgoZGlzdChjKGRlbUlzc3VlcyRib290RXZhbEluLCBkZW1Jc3N1ZXMkYm9vdEV2YWxPdXQpKSkKZGVtRGlzdE08LWFzLm1hdHJpeChkZW1EaXN0TVstKDE6MTAwKSwtKDEwMToyMDApXSkKZGVtRGlzdFYgPC0gZGVtRGlzdE1bbG93ZXIudHJpKGRlbURpc3RNKV0KCnJlcERpc3RNPC1hcy5tYXRyaXgoZGlzdChjKHJlcElzc3VlcyRib290RXZhbEluLCByZXBJc3N1ZXMkYm9vdEV2YWxPdXQpKSkKcmVwRGlzdE08LWFzLm1hdHJpeChyZXBEaXN0TVstKDE6MTAwKSwtKDEwMToyMDApXSkKcmVwRGlzdFYgPC0gcmVwRGlzdE1bbG93ZXIudHJpKHJlcERpc3RNKV0KCnJlcHV0RGlzdCA8LSBkaXN0KGlzc3Vlc0ZyYW1lJHJlcHV0KQpyZXB1dE1hdHJpeCA8LSBhcy5tYXRyaXgocmVwdXREaXN0KQpyZXB1dFZlY3RvciA8LSByZXB1dE1hdHJpeFtsb3dlci50cmkocmVwdXRNYXRyaXgpXQoKcmVwdXRERGlzdCA8LSBkaXN0KGlzc3Vlc0ZyYW1lJHJlcHV0RCkKcmVwdXRETWF0cml4IDwtIGFzLm1hdHJpeChyZXB1dEREaXN0KQpyZXB1dERWZWN0b3IgPC0gcmVwdXRETWF0cml4W2xvd2VyLnRyaShyZXB1dERNYXRyaXgpXQoKaG9uZXN0RGlzdCA8LSBkaXN0KGlzc3Vlc0ZyYW1lJGhvbmVzdCkKaG9uZXN0TWF0cml4IDwtIGFzLm1hdHJpeChob25lc3REaXN0KQpob25lc3RWZWN0b3IgPC0gaG9uZXN0TWF0cml4W2xvd2VyLnRyaShob25lc3RNYXRyaXgpXQoKY2hhbmdlRGlzdCA8LSBkaXN0KGlzc3Vlc0ZyYW1lJGNoYW5nZSkKY2hhbmdlTWF0cml4IDwtIGFzLm1hdHJpeChjaGFuZ2VEaXN0KQpjaGFuZ2VWZWN0b3IgPC0gY2hhbmdlTWF0cml4W2xvd2VyLnRyaShjaGFuZ2VNYXRyaXgpXQoKcG9saXRpY0Rpc3QgPC0gZGlzdChpc3N1ZXNGcmFtZSRwb2xpdGljKQpwb2xpdGljTWF0cml4IDwtIGFzLm1hdHJpeChwb2xpdGljRGlzdCkKcG9saXRpY1ZlY3RvciA8LSBwb2xpdGljTWF0cml4W2xvd2VyLnRyaShwb2xpdGljTWF0cml4KV0KCmJyZWFkdGhEaXN0IDwtIGRpc3QoaXNzdWVzRnJhbWUkYnJlYWR0aCkKYnJlYWR0aE1hdHJpeCA8LSBhcy5tYXRyaXgoYnJlYWR0aERpc3QpCmJyZWFkdGhWZWN0b3IgPC0gYnJlYWR0aE1hdHJpeFtsb3dlci50cmkoYnJlYWR0aE1hdHJpeCldCgpmdWxsTWF0IDwtIGFzLmRhdGEuZnJhbWUobWF0cml4KG5jb2w9MTYpKQp1SWRzPC11bmlxdWUobG9uZ0RmJHN1YklEKQpmb3IoaSBpbiAxOmxlbmd0aCh1SWRzKSl7CiAgaiA8LSB1SWRzW2ldCiAgCiAgZGlzdE1hdHJpeCA8LSBhcy5tYXRyaXgoYWxsRGlzdHNbW2ldXSkKICBkaXN0VmVjdG9yIDwtIGRpc3RNYXRyaXhbbG93ZXIudHJpKGRpc3RNYXRyaXgpXQogIAogIGRpc3RNYXRyaXhPdXQgPC0gYXMubWF0cml4KGFsbERpc3RzT3V0W1tpXV0pCiAgZGlzdFZlY3Rvck91dCA8LSBkaXN0TWF0cml4T3V0W2xvd2VyLnRyaShkaXN0TWF0cml4T3V0KV0KICAKICBkaXN0TWF0cml4SW4gPC0gYXMubWF0cml4KGFsbERpc3RzSW5bW2ldXSkKICBkaXN0VmVjdG9ySW4gPC0gZGlzdE1hdHJpeE91dFtsb3dlci50cmkoZGlzdE1hdHJpeEluKV0KICAKICBpZiggYXMuY2hhcmFjdGVyKHVuaXF1ZShsb25nRGYkcGFydHlOW2xvbmdEZiRzdWJJRD09al0pKT09IlJlcCIgKXsKICAgIHBhcnR5RGlzdFYgPC0gcmVwRGlzdFYKICB9ZWxzZSBpZiggYXMuY2hhcmFjdGVyKHVuaXF1ZShsb25nRGYkcGFydHlOW2xvbmdEZiRzdWJJRD09al0pKT09IkRlbSIgKXsKICAgIHBhcnR5RGlzdFYgPC0gZGVtRGlzdFYKICB9CiAgCiAgc3ViTWF0IDwtIGNiaW5kKGRhdGEuZnJhbWUoc3ViSUQ9aixkaXN0PWRpc3RWZWN0b3IsUmVwTj11bmlxdWUobG9uZ0RmJFJlcE5bbG9uZ0RmJHN1YklEPT1qXSksIHBhcnR5Tj11bmlxdWUobG9uZ0RmJHBhcnR5Tltsb25nRGYkc3ViSUQ9PWpdKSwgSW5mbz11bmlxdWUobG9uZ0RmJEluZm9bbG9uZ0RmJHN1YklEPT1qXSksIFJlcD11bmlxdWUobG9uZ0RmJFJlcFtsb25nRGYkc3ViSUQ9PWpdKSwgcmVwdXREID0gcmVwdXRWZWN0b3IsIHJlcHV0REQgPSByZXB1dERWZWN0b3IsIGNoYW5nZUQgPSBjaGFuZ2VWZWN0b3IsIGhvbmVzdEQgPSBob25lc3RWZWN0b3IsIHBvbGl0aWNEID0gcG9saXRpY1ZlY3RvciwgYnJlYWR0aEQgPSBicmVhZHRoVmVjdG9yLCBkaXN0T3V0ID0gZGlzdFZlY3Rvck91dCwgZGlzdEluID0gZGlzdFZlY3RvckluLCBkaXN0UGFydHkgID0gcGFydHlEaXN0ViwgY29yciA9IGNvclZlY3RvciApKQogIG5hbWVzKGZ1bGxNYXQpIDwtIGNvbG5hbWVzKHN1Yk1hdCkKICBmdWxsTWF0IDwtIHJiaW5kKGZ1bGxNYXQsIHN1Yk1hdCkKfQoKI3ggPC0gYygic3ViSUQiLCJkaXN0IikKI2Z1bGxEaXN0RGYgPC0gYXMuZGF0YS5mcmFtZShmdWxsTWF0KQojbmFtZXMoZnVsbERpc3REZikgPC0geApmdWxsRGlzdERmIDwtIGFzLmRhdGEuZnJhbWUoZnVsbE1hdCkKZnVsbERpc3REZjwtZnVsbERpc3REZlshaXMubmEoZnVsbERpc3REZiRzdWJJRCksXQoKZnVsbERpc3REZiRkaXN0U1RyYW5zIDwtIDEvKDErZnVsbERpc3REZiRkaXN0KQpmdWxsRGlzdERmJGRpc3RFVHJhbnMgPC0gMS8oZXhwKGZ1bGxEaXN0RGYkZGlzdCkpCgojZnVsbERpc3REZiA8LSBtZXJnZShmdWxsRGlzdERmLCBsb25nRGZbYygic3ViSUQiLCJSZXBOIiwicGFydHlOIiwiSW5mbyIpXSwgYnkgPSAic3ViSUQiKQoKZnVsbERpc3REZiA8LSBtZXJnZShmdWxsRGlzdERmLCBpbmREaWZmRGYsIGJ5ID0gInN1YklEIikKCmNvbG5hbWVzKGZ1bGxEaXN0RGYpCgpmdWxsRGlzdERmIDwtIGZ1bGxEaXN0RGYgJT4lIHNlbGVjdChzdWJJRCwgZGlzdCwgUmVwTiwgcGFydHlOLCBJbmZvLCBSZXAsIGNvcnIsIGRpc3RTVHJhbnMsIGRpc3RFVHJhbnMsIGFmZlBvbDpmYWxzaWZ5LCBQb2xpdCwgcG9sU3RyZW5ndGgpCgp3cml0ZS5jc3YoZnVsbERpc3REZiwgIn4vR29vZ2xlIERyaXZlL1ZvbHVtZXMvUmVzZWFyY2ggUHJvamVjdC9QcmVmZXJlbmNlIEZhbHNpZmljYXRpb24vQW5hbHlzaXMvb3V0cHV0L2Rpc3RhbmNlRGYuY3N2IikKCmFycm93Ojp3cml0ZV9wYXJxdWV0KGZ1bGxEaXN0RGYsICJ+L0dvb2dsZSBEcml2ZS9Wb2x1bWVzL1Jlc2VhcmNoIFByb2plY3QvUHJlZmVyZW5jZSBGYWxzaWZpY2F0aW9uL0FuYWx5c2lzL291dHB1dC9kaXN0YW5jZURmLnBhcnF1ZXQiKQpgYGAKCmBgYHtyfQpsb25nRGYyYzwtIGxvbmdEZjJbYygic3ViSUQiLCJpc3N1ZXMiLCJldmFsIildCmxvbmdEZjJjIDwtIGxvbmdEZjJjW29yZGVyKGxvbmdEZjJjJHN1YklELCBsb25nRGYyYyRpc3N1ZXMpLF0Kd2lkZURmIDwtIGxvbmdEZjJjICU+JSBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gaXNzdWVzLCB2YWx1ZXNfZnJvbSA9IGV2YWwpCgpjb3JNYXQgPC0gd2lkZURmICU+JSBzZWxlY3QoYDFgOmAxMDBgKSAlPiUgY29yKC4sdXNlPSJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQpjb3JNYXRaIDwtIHBzeWNoOjpmaXNoZXJ6KGNvck1hdCkKY29yVmVjdG9yIDwtIGNvck1hdFpbbG93ZXIudHJpKGNvck1hdFopXQpgYGAKCmBgYHtyfQpjb2xuYW1lcyhjb3JNYXQpIDwtIGxvbmdEZjIkbGFiZWwueFttYXRjaCh1bmlxdWUobG9uZ0RmMiRpc3N1ZXMpLCBsb25nRGYyJGlzc3VlcykgXQpyb3duYW1lcyhjb3JNYXQpIDwtIGxvbmdEZjIkbGFiZWwueFttYXRjaCh1bmlxdWUobG9uZ0RmMiRpc3N1ZXMpLCBsb25nRGYyJGlzc3VlcykgXQpqcGVnKCJ+L0Rlc2t0b3AvdGVzdC5wbmciLCBoZWlnaHQ9MTAsIHdpZHRoPTE1LCB1bml0cz0iaW4iLHJlcz0zMDApCmhlYXRtYXAoY29yTWF0LCBDb2x2ID0gIlJvd3YiLCBzeW1tPVRSVUUsIGNleFJvdz0uNSwgY2V4Q29sPS41KQpkZXYub2ZmKCkKYGBgCgpgYGB7cn0KanBlZygifi9EZXNrdG9wL3Rlc3QucG5nIiwgaGVpZ2h0PTEyLCB3aWR0aD0zMCwgdW5pdHM9ImluIixyZXM9MzAwKQpvdXRwaG08LXBoZWF0bWFwKGNvck1hdCwgZm9udHNpemVfcm93ID0gNiwgZm9udHNpemVfY29sID0gNiwgYW5nbGVfY29sID0gNDUsIGFuZ2xlX3JvdyA9NDUsIHdpZHRoPTEwMCwgaGVpZ2h0ID0gMjAwICkKb3V0cGhtCmRldi5vZmYoKQpvdXRwaG0KYGBgCgpgYGB7cn0Kb3V0PC1oZWF0bWFwbHk6OmdnaGVhdG1hcChjb3JNYXQsIGdyaWRfZ2FwPTIsIGNvbG9yYmFyX2xlbj01MCwgZ3JpZF9zaXplID0gNSAsIFJvd3Y9b3V0cGhtW1sxXV0sIENvbHY9b3V0cGhtW1syXV0sIHJldkM9VFJVRSwgZm9udHNpemVfcm93ID0gOC41LCBmb250c2l6ZV9jb2wgPSA4LjUsIGFuZ2xlX2NvbCA9IDQ1LCBhbmdsZV9yb3cgPTQ1LCAgbGltaXRzID0gYygtMSwgMSksIGNvbG9ycyA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwobiA9IDcsIG5hbWUgPSAiUmRZbEJ1IikpKSgxMDApKQpqcGVnKCJ+L0Rlc2t0b3AvdGVzdC5wbmciLCBoZWlnaHQ9MTUsIHdpZHRoPTIwLCB1bml0cz0iaW4iLHJlcz0zMDApCm91dApkZXYub2ZmKCkKYGBgCgpgYGB7cn0Kb3V0PC1oZWF0bWFwbHk6OmdnaGVhdG1hcChjb3JNYXQsIGNvbG9yYmFyX2xlbj01MCwgZ3JpZF9zaXplID0gNSAsIFJvd3Y9b3V0cGhtW1sxXV0sIENvbHY9b3V0cGhtW1syXV0sIHJldkM9VFJVRSwgZm9udHNpemVfcm93ID0gOC41LCBmb250c2l6ZV9jb2wgPSA4LjUsIGFuZ2xlX2NvbCA9IDQ1LCBhbmdsZV9yb3cgPTQ1LCAgbGltaXRzID0gYygtMSwgMSksIGNvbG9ycyA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwobiA9IDcsIG5hbWUgPSAiUmRZbEJ1IikpKSgxMDApKQpvdXQKZ2dzYXZlKCJ+L0Rlc2t0b3AvdGVzdDIucG5nIiwgZHBpPTMwMCx1bml0cz0iaW4iLGhlaWdodD0yMCx3aWR0aD0yMCkKYGBgCgoKCgpgYGB7cn0KaGVhdG1hcGx5X2Nvcihyb3VuZChjb3JNYXQsMyksIFJvd3Y9b3V0cGhtW1sxXV0sIENvbHY9b3V0cGhtW1syXV0sIHJldkM9VFJVRSwgZm9udHNpemVfcm93ID0gMi41LCBmb250c2l6ZV9jb2wgPSAyLjUsIGFuZ2xlX2NvbCA9IDQ1LCBhbmdsZV9yb3cgPTQ1LCAgbGltaXRzID0gYygtMSwgMSksIGNvbG9ycyA9IGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwobiA9IDcsIG5hbWUgPQogICJSZFlsQnUiKSkpKDEwMCkgKQpgYGAKCgpgYGB7cn0KbWRzMjwtY29yTWF0ICU+JQogIHBzeWNoOjpjb3IyZGlzdCguKSAlPiUKICBNQVNTOjppc29NRFMoaz0yKSAlPiUKICAuJHBvaW50cyAlPiUKICBhc190aWJibGUoKQpjb2xuYW1lcyhtZHMyKSA8LSBjKCJEaW0uMSIsICJEaW0uMiIpCmxpYnJhcnkoZ2dwdWJyKQpnZ3NjYXR0ZXIobWRzMiwgeCA9ICJEaW0uMSIsIHkgPSAiRGltLjIiLCAKICAgICAgICAgIGxhYmVsID0gbG9uZ0RmMiRsYWJlbC54W21hdGNoKHVuaXF1ZShsb25nRGYyJGlzc3VlcyksIGxvbmdEZjIkaXNzdWVzKSBdLAogICAgICAgICAgZm9udC5sYWJlbCA9IGMoNSwgImJvbGQiLCAiYmxhY2siKSwKICAgICAgICAgIHNpemUgPSAxLAogICAgICAgICAgcmVwZWwgPSBUUlVFKQpgYGAKCgpgYGB7cn0KYWxsRGlzdHMgPC0gdGFwcGx5KGxvbmdEZjIkZXZhbCwgbG9uZ0RmMiRzdWJJRCwgZGlzdCkKCmlzc3Vlc0ZyYW1lIDwtIGxvbmdEZjJbbWF0Y2godW5pcXVlKGxvbmdEZjIkaXNzdWVzKSwgMToxMDApLF0KCmFsbERpc3RzT3V0IDwtIHRhcHBseShsb25nRGYyJGJvb3RFdmFsT3V0LCBsb25nRGYyJHN1YklELCBkaXN0KQoKYWxsRGlzdHNJbiA8LSB0YXBwbHkobG9uZ0RmMiRib290RXZhbEluLCBsb25nRGYyJHN1YklELCBkaXN0KQoKZGVtSXNzdWVzIDwtIGRlbURmW21hdGNoKHVuaXF1ZShkZW1EZiRpc3N1ZXMpLCAxOjEwMCksXQpyZXBJc3N1ZXMgPC0gcmVwRGZbbWF0Y2godW5pcXVlKHJlcERmJGlzc3VlcyksIDE6MTAwKSxdCgpkZW1EaXN0TTwtYXMubWF0cml4KGRpc3QoYyhkZW1Jc3N1ZXMkYm9vdEV2YWxJbiwgZGVtSXNzdWVzJGJvb3RFdmFsT3V0KSkpCmRlbURpc3RNPC1hcy5tYXRyaXgoZGVtRGlzdE1bLSgxOjEwMCksLSgxMDE6MjAwKV0pCmRlbURpc3RWIDwtIGRlbURpc3RNW2xvd2VyLnRyaShkZW1EaXN0TSldCgpyZXBEaXN0TTwtYXMubWF0cml4KGRpc3QoYyhyZXBJc3N1ZXMkYm9vdEV2YWxJbiwgcmVwSXNzdWVzJGJvb3RFdmFsT3V0KSkpCnJlcERpc3RNPC1hcy5tYXRyaXgocmVwRGlzdE1bLSgxOjEwMCksLSgxMDE6MjAwKV0pCnJlcERpc3RWIDwtIHJlcERpc3RNW2xvd2VyLnRyaShyZXBEaXN0TSldCgpyZXB1dERpc3QgPC0gZGlzdChpc3N1ZXNGcmFtZSRyZXB1dCkKcmVwdXRNYXRyaXggPC0gYXMubWF0cml4KHJlcHV0RGlzdCkKcmVwdXRWZWN0b3IgPC0gcmVwdXRNYXRyaXhbbG93ZXIudHJpKHJlcHV0TWF0cml4KV0KCnJlcHV0RERpc3QgPC0gZGlzdChpc3N1ZXNGcmFtZSRyZXB1dEQpCnJlcHV0RE1hdHJpeCA8LSBhcy5tYXRyaXgocmVwdXRERGlzdCkKcmVwdXREVmVjdG9yIDwtIHJlcHV0RE1hdHJpeFtsb3dlci50cmkocmVwdXRETWF0cml4KV0KCmhvbmVzdERpc3QgPC0gZGlzdChpc3N1ZXNGcmFtZSRob25lc3QpCmhvbmVzdE1hdHJpeCA8LSBhcy5tYXRyaXgoaG9uZXN0RGlzdCkKaG9uZXN0VmVjdG9yIDwtIGhvbmVzdE1hdHJpeFtsb3dlci50cmkoaG9uZXN0TWF0cml4KV0KCmNoYW5nZURpc3QgPC0gZGlzdChpc3N1ZXNGcmFtZSRjaGFuZ2UpCmNoYW5nZU1hdHJpeCA8LSBhcy5tYXRyaXgoY2hhbmdlRGlzdCkKY2hhbmdlVmVjdG9yIDwtIGNoYW5nZU1hdHJpeFtsb3dlci50cmkoY2hhbmdlTWF0cml4KV0KCnBvbGl0aWNEaXN0IDwtIGRpc3QoaXNzdWVzRnJhbWUkcG9saXRpYykKcG9saXRpY01hdHJpeCA8LSBhcy5tYXRyaXgocG9saXRpY0Rpc3QpCnBvbGl0aWNWZWN0b3IgPC0gcG9saXRpY01hdHJpeFtsb3dlci50cmkocG9saXRpY01hdHJpeCldCgpicmVhZHRoRGlzdCA8LSBkaXN0KGlzc3Vlc0ZyYW1lJGJyZWFkdGgpCmJyZWFkdGhNYXRyaXggPC0gYXMubWF0cml4KGJyZWFkdGhEaXN0KQpicmVhZHRoVmVjdG9yIDwtIGJyZWFkdGhNYXRyaXhbbG93ZXIudHJpKGJyZWFkdGhNYXRyaXgpXQoKI2Rpc3QxIDwtIGxvd2VyLnRyaShhcy5tYXRyaXgoYWxsRGlzdHNbWzFdXSkpCiNkaXN0MSA8LSBhcy5tYXRyaXgoYWxsRGlzdHNbWzFdXSkKI2Rpc3QyIDwtIGRpc3QxW2xvd2VyLnRyaShkaXN0MSldCgojZnVsbE1hdCA8LSBtYXRyaXgobmNvbD0yKQpmdWxsTWF0MiA8LSBhcy5kYXRhLmZyYW1lKG1hdHJpeChuY29sPTE2KSkKdUlkczwtdW5pcXVlKGxvbmdEZjIkc3ViSUQpCmZvcihpIGluIDE6bGVuZ3RoKHVJZHMpKXsKICBqIDwtIHVJZHNbaV0KICAKICBkaXN0TWF0cml4IDwtIGFzLm1hdHJpeChhbGxEaXN0c1tbaV1dKQogIGRpc3RWZWN0b3IgPC0gZGlzdE1hdHJpeFtsb3dlci50cmkoZGlzdE1hdHJpeCldCiAgCiAgZGlzdE1hdHJpeE91dCA8LSBhcy5tYXRyaXgoYWxsRGlzdHNPdXRbW2ldXSkKICBkaXN0VmVjdG9yT3V0IDwtIGRpc3RNYXRyaXhPdXRbbG93ZXIudHJpKGRpc3RNYXRyaXhPdXQpXQogIAogIGRpc3RNYXRyaXhJbiA8LSBhcy5tYXRyaXgoYWxsRGlzdHNJbltbaV1dKQogIGRpc3RWZWN0b3JJbiA8LSBkaXN0TWF0cml4T3V0W2xvd2VyLnRyaShkaXN0TWF0cml4SW4pXQogIAogIGlmKCBhcy5jaGFyYWN0ZXIodW5pcXVlKGxvbmdEZjIkcGFydHlOW2xvbmdEZjIkc3ViSUQ9PWpdKSk9PSJSZXAiICl7CiAgICBwYXJ0eURpc3RWIDwtIHJlcERpc3RWCiAgfWVsc2UgaWYoIGFzLmNoYXJhY3Rlcih1bmlxdWUobG9uZ0RmMiRwYXJ0eU5bbG9uZ0RmMiRzdWJJRD09al0pKT09IkRlbSIgKXsKICAgIHBhcnR5RGlzdFYgPC0gZGVtRGlzdFYKICB9CiAgCiAgc3ViTWF0IDwtIGNiaW5kKGRhdGEuZnJhbWUoc3ViSUQ9aixkaXN0PWRpc3RWZWN0b3IsUmVwTj11bmlxdWUobG9uZ0RmMiRSZXBOW2xvbmdEZjIkc3ViSUQ9PWpdKSwgcGFydHlOPXVuaXF1ZShsb25nRGYyJHBhcnR5Tltsb25nRGYyJHN1YklEPT1qXSksIEluZm89dW5pcXVlKGxvbmdEZjIkSW5mb1tsb25nRGYyJHN1YklEPT1qXSksIFJlcD11bmlxdWUobG9uZ0RmMiRSZXBbbG9uZ0RmMiRzdWJJRD09al0pLCByZXB1dEQgPSByZXB1dFZlY3RvciwgcmVwdXRERCA9IHJlcHV0RFZlY3RvciwgY2hhbmdlRCA9IGNoYW5nZVZlY3RvciwgaG9uZXN0RCA9IGhvbmVzdFZlY3RvciwgcG9saXRpY0QgPSBwb2xpdGljVmVjdG9yLCBicmVhZHRoRCA9IGJyZWFkdGhWZWN0b3IsIGRpc3RPdXQgPSBkaXN0VmVjdG9yT3V0LCBkaXN0SW4gPSBkaXN0VmVjdG9ySW4sIGRpc3RQYXJ0eSAgPSBwYXJ0eURpc3RWLCBjb3JyID0gY29yVmVjdG9yICkpCiAgbmFtZXMoZnVsbE1hdDIpIDwtIGNvbG5hbWVzKHN1Yk1hdCkKICBmdWxsTWF0MiA8LSByYmluZChmdWxsTWF0Miwgc3ViTWF0KQp9CgojeCA8LSBjKCJzdWJJRCIsImRpc3QiKQojZnVsbERpc3REZiA8LSBhcy5kYXRhLmZyYW1lKGZ1bGxNYXQpCiNuYW1lcyhmdWxsRGlzdERmKSA8LSB4CmZ1bGxEaXN0RGYyIDwtIGFzLmRhdGEuZnJhbWUoZnVsbE1hdDIpCmZ1bGxEaXN0RGYyIDwtIGZ1bGxEaXN0RGYyWyFpcy5uYShmdWxsRGlzdERmMiRzdWJJRCksXQoKZnVsbERpc3REZjIkZGlzdFNUcmFucyA8LSAxLygxK2Z1bGxEaXN0RGYyJGRpc3QpCmZ1bGxEaXN0RGYyJGRpc3RFVHJhbnMgPC0gMS8oZXhwKGZ1bGxEaXN0RGYyJGRpc3QpKQoKaW5kRGlmZkRmMiA8LSBpbmREaWZmRGYyICU+JSBzZWxlY3Qoc3ViSUQsIFBvbGl0Lng6ZmFsc2lmeSkKZnVsbERpc3REZjIgPC0gbWVyZ2UoZnVsbERpc3REZjIsIGluZERpZmZEZjIsIGJ5ID0gInN1YklEIikKCmZ1bGxEaXN0RGYyJHBvbFN0cmVuZ3RoIDwtIGFicyg0LWZ1bGxEaXN0RGYyJFBvbGl0LngpCgpmdWxsRGlzdERmMiA8LSBmdWxsRGlzdERmMiAlPiUgc2VsZWN0KHN1YklELCBkaXN0LCBSZXBOLCBwYXJ0eU4sIEluZm8sIFJlcCwgY29yciwgZGlzdFNUcmFucywgZGlzdEVUcmFucywgYWZmUG9sOmZhbHNpZnksIFBvbGl0LngsIHBvbFN0cmVuZ3RoKQoKd3JpdGUuY3N2KGZ1bGxEaXN0RGYyLCAiL1ZvbHVtZXMvR29vZ2xlRHJpdmUvTXkgRHJpdmUvVm9sdW1lcy9SZXNlYXJjaCBQcm9qZWN0L1ByZWZlcmVuY2UgRmFsc2lmaWNhdGlvbi9TdHVkeSAyIEFuYWx5c2lzL291dHB1dC9kaXN0YW5jZURmMi5jc3YiKQoKYXJyb3c6OndyaXRlX3BhcnF1ZXQoZnVsbERpc3REZjIsICIvVm9sdW1lcy9Hb29nbGVEcml2ZS9NeSBEcml2ZS9Wb2x1bWVzL1Jlc2VhcmNoIFByb2plY3QvUHJlZmVyZW5jZSBGYWxzaWZpY2F0aW9uL1N0dWR5IDIgQW5hbHlzaXMvb3V0cHV0L2Rpc3RhbmNlRGYyLnBhcnF1ZXQiKQpgYGA=